package domain;


import interfaces.IPlayerManagement;

import java.io.IOException;
import java.io.Serializable;
import java.util.Vector;

import persistence.FilePersistenceManager;
import persistence.IPersistenceManager;
import valueObjects.game.Player;
import exception.player.NotEqualPasswordException;
import exception.player.PlayerAlreadyExistsException;
import exception.player.PlayerNotSavedException;

/**
 * This class is for managing the players.
 */
public class PlayerManagement implements Serializable, IPlayerManagement{
	
	private static final long serialVersionUID = 1L;

	public final static int MAX_PLAYERS = 6;

	private transient IPersistenceManager pManager = new FilePersistenceManager();
	
	private Vector<Player> listOfPlayers = new Vector<Player>();
	
	private Vector<Player> currentPlayers = new Vector<Player>();
	
	private Player currentPlayer;

	private String file;
	
	/**
	 * Constructor with the file where players are stored
	 * @param file
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public PlayerManagement(String file) {
		this.file = file;
		this.loadListOfPlayers();
	}
	
	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#getCurrentPlayers()
	 */
	@Override
	public Vector<Player> getCurrentPlayers() {
		return currentPlayers;
	}

	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#getListOfPlayers()
	 */
	@Override
	public Vector<Player> getListOfPlayers() {
		return this.listOfPlayers;
	}

	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#addNewPlayer(valueObjects.game.Player)
	 */
	@Override
	public void addNewPlayer(Player player) {
		this.listOfPlayers.add(player);
	}

	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#getNextPlayer(valueObjects.game.Player)
	 */
	public Player getNextPlayer(Player currentPlayer) {
		for (short i = 0; i < this.currentPlayers.size(); i++) {
			if(this.currentPlayers.get(i).equals(currentPlayer)){
				try {
					return this.currentPlayers.get(i + 1);
				} catch (Exception e) {
					return this.currentPlayers.get(0);
				}
			}
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#loadListOfPlayers()
	 */
	@Override
	public void loadListOfPlayers() {
		if (this.loadPlayers() <= 0) {
			this.listOfPlayers = new Vector<Player>();
		}
	}
	
	/**
	 * Loads a single saved player from a file
	 * @param file
	 * @throws IOException
	 * @throws ClassNotFoundException
	 */
	private short loadPlayers(){
		try {
			this.pManager.openForReadingSer(this.file);
			// loading player list
			this.listOfPlayers = (Vector<Player>) this.pManager.loadPlayers();
			this.pManager.close();
		} catch (ClassNotFoundException e) {
			return 0;
		} catch (IOException e) {
			return -1;
		}
		return 1;
	}
	
	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#saveNewPlayer(java.lang.String, java.lang.String, java.lang.String)
	 */
	@Override
	public void saveNewPlayer(String username, String passwordF, String passwordS) throws PlayerAlreadyExistsException, NotEqualPasswordException, PlayerNotSavedException {
		if(!passwordF.equals(passwordS)){
			throw new NotEqualPasswordException();
		}
		for (Player pla : this.listOfPlayers) {
			if(username.equals(pla.getName())){
				throw new PlayerAlreadyExistsException(username);
			}
		}
		Player p = new Player(username, passwordF);
		try {
			this.addNewPlayer(p);
			this.pManager.openForWritingSer("resources/Players.txt");
			this.pManager.savePlayerList(this.listOfPlayers);
			this.pManager.close();
		} catch (Exception e) {
			throw new PlayerNotSavedException(username);
		}
	}

	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#addCurrentPlayer(valueObjects.game.Player)
	 */
	@Override
	public void addCurrentPlayer(Player player) {
		if(this.currentPlayer == null){
			this.currentPlayer = player;
		}
		this.currentPlayers.add(player);
	}

	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#getCurrentPlayer(valueObjects.game.Player)
	 */
	@Override
	public Player getCurrentPlayer() {
		return this.currentPlayer;
	}
	
	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#finish(valueObjects.game.Player)
	 */
	@Override
	public void finish(Player p) {
		this.currentPlayer = getNextPlayer(currentPlayer);
	}
	/* (non-Javadoc)
	 * @see domain.IPlayerManagement#isCurrentPlayer(valueObjects.game.Player)
	 */
	@Override
	public boolean isCurrentPlayer(Player player) {
		if(this.currentPlayer.equals(player)){
			return true;
		}
		return false;
	}

	@Override
	public void setCurrentPlayer(Player p) {
		this.currentPlayer = p;
	}

	/**
	 * Resets the interaction cards
	 */
	@Override
	public void removeInteraction() {
		for (Player p : this.currentPlayers) {
			p.revertCardsInteract();
		}
	}

}